import { SearchOutlined, ReloadOutlined } from '@ant-design/icons'
import { truthy } from '@gnlab/utils'
import { message, Checkbox, Popconfirm, Radio, Input, Select, Button, Form } from 'antd'
import { OrderedSet } from 'immutable'
import { Empty, EditModal } from '@/desktop/components'
import { ChooseAccountModal } from '@/desktop/components/ChooseAccount'
import { useChooseAll } from '@/desktop/logics/choose-all'
import { useConfirmQywxLimit } from '@/desktop/logics/qywx/limit'
import { colors } from '@/desktop/styles'
import { useStreams } from '@/lib/utils'
import services from '@/services'
import type { BaseAccount } from '@/services/auth'
import { AccountQywxStatus } from '@/services/qywxs'
import { AccountItem } from './account-item'
import EditPassword from './edit-password'
import EditPermission from './edit-permission'
import './index.module.less'
import {
  useAccountAndQywxs,
  useAccountFilter,
  useQywxFilter,
  useChooseQywxs,
  useQywxActions,
} from './logics'
import { QywxItem } from './qywx-item'

const getAccountId = (account: BaseAccount) => account.id

export default function Accounts() {
  const [currentAccount] = useStreams(services.auth.account$)
  const canLogIn = useConfirmQywxLimit()

  const { accounts, accountQywxMap, loadQywxs, loading } = useAccountAndQywxs()
  const { groups, selectedGroup, setSelectedGroup, filteredAccounts, accountGroupsMap } =
    useAccountFilter(accounts)

  const [choosedAccounts, setChoosedAccounts] = useState(OrderedSet<string>())
  const switchChooseAccount = useCallback((accountId: string) => {
    setChoosedAccounts(set => (set.has(accountId) ? set.delete(accountId) : set.add(accountId)))
  }, [])
  // 账号列表变动时，把没显示出来的账号移除选择
  useEffect(() => {
    const existsIds = OrderedSet(filteredAccounts.map(v => v.id))
    const cleared = choosedAccounts.intersect(existsIds)
    if (cleared.size !== choosedAccounts.size) setChoosedAccounts(cleared)
  }, [filteredAccounts, choosedAccounts])

  // 全选状态
  const { chooseAll, chooseReverse, chooseAllProps } = useChooseAll({
    list: accounts,
    getId: getAccountId,
    choosed: choosedAccounts,
    setChoosed: setChoosedAccounts,
    keep: false,
  })

  function goObserving() {
    if (!choosedAccounts.size) return
    services.auth.observing.go(choosedAccounts.toArray())
  }

  const [rebooting, setRebooting] = useState<OrderedSet<string>>(() => OrderedSet())
  const {
    accountId,
    mode,
    search,
    dispatch: filterDispatch,
    accountQywxs,
    showingQywxs,
    count,
  } = useQywxFilter(accounts, accountQywxMap, rebooting)
  const { choosedQywxs, switchChooseQywx, chooseAllStatus, switchChooseAll, resetChoose } =
    useChooseQywxs(showingQywxs)

  const [editingPermissions, setEditingPermissions] = useState<string | null>(null) // 正在编辑权限的 account
  const finishEditPermissions = useCallback(() => setEditingPermissions(null), [])

  const [editingPassword, setEditingPassword] = useState<string | null>(null) // 正在修改密码的 account
  const finishEditPassword = useCallback(() => setEditingPassword(null), [])

  const [transfering, setTransfering] = useState<string[] | null>(null)
  const { getActions, transferQywxs } = useQywxActions(
    accountQywxs,
    accounts,
    loadQywxs,
    setTransfering,
    rebooting,
    setRebooting,
  )
  const executeTransfer = useCallback(
    async (choosed: BaseAccount[]) => {
      if (!transfering) return
      setTransfering(null)

      const result = await transferQywxs(choosed[0]!, transfering)
      if (result === true) void message.success('转交成功')
      else void message.warning(result)
    },
    [transfering, transferQywxs],
  )

  const batchActions = getActions(
    [...choosedQywxs].map(wxid => showingQywxs.find(v => v.wxid === wxid)!),
  ).map(action => ({
    ...action,
    execute() {
      action.execute()
      resetChoose()
    },
  }))

  const [registering, setRegistering] = useState(false)
  const finishRegister = useCallback(() => {
    setRegistering(false)
    void loadQywxs()
  }, [loadQywxs])

  if (!currentAccount) return null

  return <div styleName="wrap">
    <div styleName="accounts-wrap">
      {groups && groups.length ? (
        <div css={s.groups}>
          <Select
            options={[
              { label: '全部账号', value: null },
              ...groups.map(g => ({ label: g.name, value: g.id })),
            ]}
            value={selectedGroup?.id ?? null}
            onChange={(value: number | null) =>
              setSelectedGroup(value === null ? null : groups.find(v => v.id === value)!)
            }
          />
        </div>
      ) : (
        <header>账号列表</header>
      )}

      <div css={s.accBatchActions}>
        <aside>
          <Checkbox {...chooseAllProps} />
          <a onClick={chooseAll}>全选</a>
          <span className="sep"> / </span>
          <a onClick={chooseReverse}>反选</a>
        </aside>
        <Button type="link" disabled={choosedAccounts.size === 0} onClick={goObserving}>
          批量查看聊天
        </Button>
      </div>

      <div styleName="accounts">
        {filteredAccounts.map(acc => <AccountItem
          key={acc.id}
          item={acc}
          groups={accountGroupsMap.get(acc.id) ?? []}
          qywxCount={
            accountQywxMap.get(acc.id)?.filter(v => v.status === AccountQywxStatus.Online).length ??
            0
          }
          operatorAccount={currentAccount}
          isSelected={accountId === acc.id}
          onSelect={id => filterDispatch({ type: 'select-account', id })}
          isChoosed={choosedAccounts.has(acc.id)}
          switchChoose={switchChooseAccount}
          onEditPermissions={setEditingPermissions}
          onEditPassword={setEditingPassword}
        />)}
      </div>
      <EditPermission
        isSuperAdmin={truthy(currentAccount.isSuperAdmin)}
        accountId={editingPermissions}
        onClose={finishEditPermissions}
      />
      <EditPassword accountId={editingPassword} onClose={finishEditPassword} />
    </div>

    <div styleName="qywxs-panel">
      <div styleName="filter">
        <Radio.Group
          value={mode}
          onChange={e =>
            filterDispatch({ type: 'set-mode', mode: e.target.value as 'online' | 'offline' })
          }
        >
          <Radio.Button value="online" disabled={!count.online}>
            在线{count.online ? `(${count.online})` : ''}
          </Radio.Button>
          <Radio.Button value="offline" disabled={!count.offline}>
            离线{count.offline ? `(${count.offline})` : ''}
          </Radio.Button>
        </Radio.Group>
        <Input
          prefix={<SearchOutlined />}
          placeholder="搜索企微账号"
          value={search}
          onChange={e => filterDispatch({ type: 'set-search', search: e.target.value })}
        />
        <div styleName="refresh-wrap">
        {!loading ? (
          <div styleName="refresh" onClick={loadQywxs}>
            <ReloadOutlined />
            刷新
          </div>
        ) : (
          <div styleName="refresh loading">
            <ReloadOutlined />
            正在刷新...
          </div>
        )}
        </div>
        <Button type="primary" onClick={() => setRegistering(true)}>账号注册</Button>
      </div>

      {/*{mode === 'offline' ? (*/}
      {/*  <div styleName="offline-tips">*/}
      {/*    离线账号保存了登录信息，大多数情况下无需扫码即可重新登录上线。少数登录信息失效的情况下，仍需要重登。*/}
      {/*  </div>*/}
      {/*) : null}*/}

      {!showingQywxs.length ? (
        <div styleName="empty-qywxs">
          <Empty description="没有符合条件的企业微信" />
        </div>
      ) : null}

      {showingQywxs.length ? (
        <div styleName="qywxs-wrap">
          <header>
            <Checkbox
              indeterminate={chooseAllStatus === 2}
              checked={chooseAllStatus === 1}
              onChange={switchChooseAll}
            />
            <span styleName="tip">企业微信列表</span>
            <span styleName="wxid">wxid</span>
            <span styleName="hostname">hostname</span>
            {batchActions.length ? (
              <div styleName="batch-actions">
                <span>批量操作 {choosedQywxs.size} 个企业微信：</span>
                {batchActions.map(({ title, needConfirm, execute }) => {
                  if (needConfirm) {
                    return <Popconfirm
                      key={title}
                      title={`确定要${title}选中的企业微信吗？`}
                      onConfirm={execute}
                    >
                      <a>{title}</a>
                    </Popconfirm>
                  } else {
                    return <a key={title} onClick={execute}>
                      {title}
                    </a>
                  }
                })}
              </div>
            ) : null}
          </header>
          <div styleName="qywxs">
            {showingQywxs.map(qywx => <QywxItem
              key={qywx.wxid}
              item={qywx}
              rebooting={rebooting.has(qywx.wxid)}
              actions={getActions([qywx])}
              choosed={choosedQywxs.has(qywx.wxid)}
              switchChoose={switchChooseQywx}
              canLogIn={canLogIn}
            />)}
          </div>
        </div>
      ) : null}
    </div>

    <ChooseAccountModal
      visible={!!transfering}
      title="选择转交到的账号"
      disabled={accountId}
      onCancel={() => setTransfering(null)}
      onChoosed={executeTransfer}
    />

    <RegisterModal open={registering} onClose={finishRegister} />
  </div>
}

interface LoginFields {
  name: string
  password: string
}

interface RegisterFields extends LoginFields {
  confirmPassword: string
}

function RegisterModal({ open, onClose }: { open: boolean, onClose: () => void }) {
  return <EditModal title="账号注册" open={open} onCancel={onClose}>
    {open ? <RegisterForm onFinish={onClose} /> : null}
  </EditModal>
}
function RegisterForm({ onFinish }: { onFinish: () => void }) {
  const [notice, setNotice] = useState('')

  const register = useCallback(async (values: RegisterFields) => {
    if (values.password !== values.confirmPassword) {
      setNotice('两次输入的密码不一致')
      return
    }
    const res = await services.auth.internal.register(values.name, values.password, false)
    if (res.success) {
      void message.success('注册成功')
      onFinish()
    } else {
      setNotice(res.error)
    }
  }, [onFinish])

  return <div css={s.register}>
    {notice ? <div className="notice">{notice}</div> : null}
    <Form<RegisterFields>
      labelCol={{ span: 5 }}
      initialValues={{ name: '', password: '', confirmPassword: '' }}
      onFinish={register}
      onValuesChange={() => setNotice('')}
    >
      <Form.Item label="用户名" name="name" rules={[{ required: true }]}>
        <Input />
      </Form.Item>
      <Form.Item label="密码" name="password" rules={[{ required: true }]}>
        <Input type="password" />
      </Form.Item>
      <Form.Item label="确认密码" name="confirmPassword" rules={[{ required: true }]}>
        <Input type="password" />
      </Form.Item>
      <div styleName="actions">
        <Button type="primary" htmlType="submit">
          注册
        </Button>
      </div>
    </Form>
  </div>
}


const s = {
  groups: css`
    padding: 0 12px 8px;
    display: flex;
    .ant-select {
      flex: 1;
    }
  `,
  accBatchActions: css`
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 12px;
    aside {
      font-size: 12px;
      .ant-checkbox-wrapper {
        margin-right: 12px;
      }
      .sep {
        color: ${colors.gray};
      }
    }
    button {
      padding: 0;
      font-size: 12px;
    }
  `,
  register: css`
    padding: 20px 20px 0;
    .notice {
      text-align: center;
      color: #ff4868;
      margin-bottom: 20px;
    }
  `
}
